﻿using LogSystem;
using System;
using System.Collections.Generic;
using UnityEngine;
using Yoozoo.Gta.Common;
using Yoozoo.Managers.ResourceManagerV2.Runtime;

namespace Yoozoo.Core.Common
{
    [Serializable]
    public class SmartResLoader
    {
        public static int ResLoadingCount = 0;
        
        [Header("任务名称")]
        public string taskName;
        private ResLoader _resLoader;
        public ResLoader ResLoader => _resLoader;
        
        private int _loadingCount;
        public int LoadingCount
        {
            get
            {
                return _loadingCount;
            }
            set
            {
                if (value < 0)
                {
                    value = 0;
                }

                ResLoadingCount -= _loadingCount;
                _loadingCount = value;
                ResLoadingCount += _loadingCount;
            }
        }
        
        private Action _completeCallback;
        private Res.ResLoadCompleteCallBack _updateCallback;

        [Header("完成回调耗时")]
        public float completeTime;
        
        public List<string> ResPathList;

        private readonly System.Diagnostics.Stopwatch _stopwatch = 
            new System.Diagnostics.Stopwatch();

        public SmartResLoader(string taskName)
        {
            this.taskName = taskName;
#if DEVELOPMENT_BUILD || UNITY_EDITOR
            ResPathList = new List<string>();
#endif
            _resLoader = ResLoader.Alloc();
        }

        
        // 只给 public SmartResLoader(string taskName) 构造的对象使用
        public void AddLoad(string resPath,Res.ResLoadCompleteCallBack callBack = null)
        {
#if DEVELOPMENT_BUILD || UNITY_EDITOR
            ResPathList.Add(resPath);
#endif
            LoadingCount++;
            //Debug.Log(LogModule.Loading, $"加载：{taskName} asset = {resPath} LoadingCount = {LoadingCount}");
            _resLoader.Add2Load(resPath,((success, name, asset) =>
            {
#if DEVELOPMENT_BUILD || UNITY_EDITOR
                ResPathList.Remove(resPath);
#endif
                LoadingCount--;
                callBack?.Invoke(success,name,asset);
                //Debug.Log(LogModule.Loading, $"加载完成：{taskName} asset = {name} LoadingCount = {LoadingCount}");
            }));
        }


        #region 构造后，不允许再增加资源加载任务

        public SmartResLoader(string taskName,string resPath,Res.ResLoadCompleteCallBack callBack = null)
        {
            this.taskName = taskName;
#if DEVELOPMENT_BUILD || UNITY_EDITOR
            ResPathList = new List<string> { resPath };
#endif
            LoadingCount = 1;
            Debug.Log(LogModule.Loading, $"加载：{taskName} asset = {resPath} LoadingCount = {LoadingCount}");
            AddUpdateCallback(callBack);
            _resLoader = ResLoader.Alloc();
            _resLoader.Add2Load(resPath,((success, name, asset) =>
            {
                try
                {
#if DEVELOPMENT_BUILD || UNITY_EDITOR
                    ResPathList.Remove(resPath);
#endif
                    _stopwatch.Reset();
                    _stopwatch.Start();
                    LoadingCount = 0;
                    _updateCallback?.Invoke(success,name,asset);
                    completeTime = _stopwatch.ElapsedMilliseconds;
                    Debug.Log(LogModule.Loading, $"加载完成：{taskName} asset = {name},完成回调耗时：{completeTime}ms");
                    _stopwatch.Stop();
                    Debug.Log(LogModule.Loading,$"加载完成：{name}");
                }
                catch (Exception e)
                {
                    Debug.LogError(LogModule.Loading,$"加载回调处理错误：taskName :{taskName}, resPath：{resPath}");
                    throw;
                }
            }));
        }

        public SmartResLoader(string taskName, List<string> resPaths,Res.ResLoadCompleteCallBack callBack = null,
            Action completeCallback = null)
        {
            if (resPaths == null)
            {
                Debug.LogError(LogModule.Loading,$"构建Loader失败：{taskName}");
                return;
            }
            
            this.taskName = taskName;
#if DEVELOPMENT_BUILD || UNITY_EDITOR
            ResPathList = new List<string>(resPaths);
#endif
            AddUpdateCallback(callBack);
            AddCompleteCallback(completeCallback);
            _resLoader = ResLoader.Alloc();
            foreach (var resPath in resPaths)
            {
                if(string.IsNullOrEmpty(resPath)) continue;
                
                LoadingCount++;
                _resLoader.Add2Load(resPath,((success, name, asset) =>
                {
#if DEVELOPMENT_BUILD || UNITY_EDITOR
                    ResPathList.Remove(resPath);
#endif
                    LoadingCount--;
                 
                    _updateCallback?.Invoke(success,name,asset);
                    //Debug.Log(LogModule.Loading,$"加载完成：{name}");
                }));
            }
        }

        #endregion
        
       

        public void Load(Action callBack = null)
        {
            if (callBack!=null)
            {
                AddCompleteCallback(callBack);
            }
            
            _resLoader.Load((() =>
            {
                LoadingCount = 0;
                completeTime = 0;
                if (_completeCallback != null)
                {
                    _stopwatch.Reset();
                    _stopwatch.Start();
                    
                    _completeCallback.Invoke();
                    
                    completeTime = _stopwatch.ElapsedMilliseconds;
                    _stopwatch.Stop();
                }
                Debug.Log(LogModule.Loading, $"Loading任务完成：{taskName},完成回调耗时：{completeTime}ms");
                ResidentHandler.Inst.GetFunction("G_Loading.loadEventSuccess").Action(taskName);
            }));
        }
        

        public void Dispose()
        {
            _resLoader.Recycle2Cache();
            _resLoader = null;
            _updateCallback = null;
            _completeCallback = null;
#if DEVELOPMENT_BUILD || UNITY_EDITOR
            ResPathList = null;
#endif
        }
        
        
        private void AddUpdateCallback(Res.ResLoadCompleteCallBack callBack)
        {
            if (callBack == null) return;
            _updateCallback = callBack;
        }
        
        private void AddCompleteCallback(Action callBack)
        {
            if (callBack == null) return;
            _completeCallback += callBack;
        }

        public override string ToString()
        {
            return taskName;
        }
    }
}
